import {asyncRoutes, constantRoutes, routerMap} from '@/router'

/**
 * 使用路由meta.roles判断当前用户是否具有权限
 * @param role_routes
 * @param route
 */
function hasPermission(role_routes, route) {
  if (route.meta && route.meta.roleRoutes) {
    return role_routes.some(role_route => route.meta.roleRoutes.includes(role_route))
  } else {
    return true
  }
}

/**
 * 将本地routerMap映射到ajax获取到的serverRouterMap
 * @param routerMap
 * @param serverRouterMap
 */
function generateAsyncRouter(routerMap, serverRouterMap) {
  serverRouterMap.forEach(function (item, index) {
    if (routerMap[item.component]) {
      item.component = routerMap[item.component]
    } else {
      item.component = routerMap['empty']
    }
    if (item.children && item.children.length > 0) {
      generateAsyncRouter(routerMap, item.children)
    }
  })
  return serverRouterMap;
}

/**
 * 生成扁平化机构路由(仅两级结构)
 * @param {允许访问的路由Tree} accessRoutes
 * 路由基本机构:
 * {
 *   name: String,
 *   path: String,
 *   component: Component,
 *   redirect: String,
 *   children: [
 *   ]
 * }
 */
function generateFlatRoutes(accessRoutes) {
  const flatRoutes = []

  for (const item of accessRoutes) {
    let childrenFflatRoutes = []
    if (item.children && item.children.length > 0) {
      childrenFflatRoutes = castToFlatRoute(item.children, '')
    }

    // 一级路由是布局路由,需要处理的只是其子路由数据
    flatRoutes.push({
      name: item.name ? item.name : '',
      path: item.path,
      component: item.component,
      redirect: item.redirect,
      children: childrenFflatRoutes
    })
  }

  return flatRoutes
}

/**
 * 将子路由转换为扁平化路由数组（仅一级）
 * @param {待转换的子路由数组} routes
 * @param {父级路由路径} parentPath
 */
function castToFlatRoute(routes, parentPath, flatRoutes = []) {
  for (const item of routes) {
    if (item.children && item.children.length > 0) {
      if (item.redirect && item.redirect !== 'noRedirect') {
        flatRoutes.push({
          name: item.name ? item.name : '',
          //path: (parentPath + '/' + item.path).substring(1),
          path: item.path,
          redirect: item.redirect,
          meta: item.meta
        })
      }
      castToFlatRoute(item.children, parentPath + '/' + item.path, flatRoutes)
    } else {
      flatRoutes.push({
        name: item.name ? item.name : '',
        //path: (parentPath + '/' + item.path).substring(1),
        path: item.path,
        component: item.component,
        meta: item.meta
      })
    }
  }

  return flatRoutes
}

/**
 * 递归过滤异步路由表
 * @param routes asyncRoutes
 * @param role_routes
 */
export function filterAsyncRoutes(routes, role_routes) {
  const res = []

  routes.forEach(route => {
    const tmp = {...route}
    if (hasPermission(role_routes, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, role_routes)
      }
      res.push(tmp)
    }
  })

  return res
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  generateRoutes({commit}, routes_obj) {
    const server_routes = routes_obj.async_routes
    const role_routes = routes_obj.role_routes
    //console.log(routes_obj.async_routes)
    const async_routes = generateAsyncRouter(routerMap, server_routes)
    // 合并数组
    let asyncRouters = [...async_routes, ...asyncRoutes]
    console.log(asyncRouters)
    return new Promise(resolve => {
      let accessedRoutes
      //console.log(role_routes.includes('admin'))
      // 判断无效
      if (role_routes.includes('admin')) {
        //accessedRoutes = asyncRoutes || []
        accessedRoutes = asyncRouters || []
      } else {
        //accessedRoutes = filterAsyncRoutes(asyncRoutes, role_routes)
        accessedRoutes = filterAsyncRoutes(asyncRouters, role_routes)
      }
      commit('SET_ROUTES', accessedRoutes)
      //resolve(accessedRoutes)
      // 支持无限级路由缓存
      const flatRoutes = generateFlatRoutes(accessedRoutes)
      console.log(flatRoutes)
      resolve(flatRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
